home *** CD-ROM | disk | FTP | other *** search
/ Resource Library: Multimedia / Resource Library: Multimedia.iso / utils / graphic / viewers / jpeg / amiga / vwjpg10b / viewjpeg.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-04-27  |  23.9 KB  |  611 lines

  1. /*
  2.  * example.c
  3.  *
  4.  * This file is not actually part of the JPEG software.  Rather, it provides
  5.  * a skeleton that may be useful for constructing applications that use the
  6.  * JPEG software as subroutines.  This code will NOT do anything useful as is.
  7.  *
  8.  * This file illustrates how to use the JPEG code as a subroutine library
  9.  * to read or write JPEG image files.  We assume here that you are not
  10.  * merely interested in converting the image to yet another image file format
  11.  * (if you are, you should be adding another I/O module to cjpeg/djpeg, not
  12.  * constructing a new application).  Instead, we show how to pass the
  13.  * decompressed image data into or out of routines that you provide.  For
  14.  * example, a viewer program might use the JPEG decompressor together with
  15.  * routines that write the decompressed image directly to a display.
  16.  *
  17.  * We present these routines in the same coding style used in the JPEG code
  18.  * (ANSI function definitions, etc); but you are of course free to code your
  19.  * routines in a different style if you prefer.
  20.  */
  21.  
  22. /*
  23.  * Include file for declaring JPEG data structures.
  24.  * This file also includes some system headers like <stdio.h>;
  25.  * if you prefer, you can include "jconfig.h" and "jpegdata.h" instead.
  26.  */
  27.  
  28. #include "jinclude.h"
  29. #ifdef INCLUDES_ARE_ANSI   
  30. #include <stdlib.h>        
  31. #endif
  32.  
  33. #define VIEWWIDTH        (320+50)
  34. #define VIEWHEIGHTLOWRES (256+20)
  35. #define VIEWHEIGHTHIRES  (512+20)
  36. #define VIEWXOFFSET  -25
  37. #define VIEWYOFFSET  -15
  38. #define VIEWDEPTH    6
  39. #define USEDCOLORREG 16
  40.  
  41. /*
  42.  * <setjmp.h> is used for the optional error recovery mechanism shown in
  43.  * the second part of the example.
  44.  */
  45.  
  46. #include <setjmp.h>
  47. #include "virtdisp.h"
  48.  
  49. struct VirtualDisplay *OpenVirtualDisplay( struct NewVirtualDisplay * );
  50. void CloseVirtualDisplay( struct VirtualDisplay * );
  51. void RefreshVirtualDisplay( struct VirtualDisplay * );
  52. extern short mouse_x( void );
  53. extern short mouse_y( void );
  54. extern void __asm transpose( register __a0 UBYTE * );
  55.  
  56. extern int glob_pixel_smoothing;
  57. extern int glob_block_smoothing;
  58. extern int glob_hires;
  59. extern int glob_grayscale;
  60. extern USHORT glob_treshold;
  61.  
  62. /******************** JPEG DECOMPRESSION SAMPLE INTERFACE *******************/
  63.  
  64. /* This half of the example shows how to read data from the JPEG decompressor.
  65.  * It's a little more refined than the above in that we show how to do your
  66.  * own error recovery.  If you don't care about that, you don't need these
  67.  * next two routines.
  68.  */
  69.  
  70.  
  71. /*
  72.  * These routines replace the default trace/error routines included with the
  73.  * JPEG code.  The example trace_message routine shown here is actually the
  74.  * same as the standard one, but you could modify it if you don't want messages
  75.  * sent to stderr.  The example error_exit routine is set up to return
  76.  * control to read_JPEG_file() rather than calling exit().  You can use the
  77.  * same routines for both compression and decompression error recovery.
  78.  */
  79.  
  80. /* These static variables are needed by the error routines. */
  81. static jmp_buf setjmp_buffer;    /* for return to caller */
  82. static external_methods_ptr emethods; /* needed for access to message_parm */
  83.  
  84.  
  85. /* Global display pointer !!! */
  86. struct VirtualDisplay *vdisp = NULL;
  87.  
  88. /* This routine is used for any and all trace, debug, or error printouts
  89.  * from the JPEG code.  The parameter is a printf format string; up to 8
  90.  * integer data values for the format string have been stored in the
  91.  * message_parm[] field of the external_methods struct.
  92.  */
  93.  
  94. METHODDEF void
  95. trace_message (const char *msgtext)
  96. {
  97. /*
  98.   fprintf(stderr, msgtext,
  99.       emethods->message_parm[0], emethods->message_parm[1],
  100.       emethods->message_parm[2], emethods->message_parm[3],
  101.       emethods->message_parm[4], emethods->message_parm[5],
  102.       emethods->message_parm[6], emethods->message_parm[7]);
  103.   fprintf(stderr, "\n");
  104. */
  105. }
  106.  
  107. /*
  108.  * The error_exit() routine should not return to its caller.  The default
  109.  * routine calls exit(), but here we assume that we want to return to
  110.  * read_JPEG_data, which has set up a setjmp context for the purpose.
  111.  * You should make sure that the free_all method is called, either within
  112.  * error_exit or after the return to the outer-level routine.
  113.  */
  114.  
  115. METHODDEF void
  116. error_exit (const char *msgtext)
  117. {
  118.   if( vdisp ) CloseVirtualDisplay( vdisp );
  119.   trace_message(msgtext);    /* report the error message */
  120.   (*emethods->free_all) ();    /* clean up memory allocation & temp files */
  121.   longjmp(setjmp_buffer, 1);    /* return control to outer routine */
  122. }
  123.  
  124.  
  125. /*
  126.  * To accept the image data from decompression, you must define four routines
  127.  * output_init, put_color_map, put_pixel_rows, and output_term.
  128.  *
  129.  * You must understand the distinction between full color output mode
  130.  * (N independent color components) and colormapped output mode (a single
  131.  * output component representing an index into a color map).  You should use
  132.  * colormapped mode to write to a colormapped display screen or output file.
  133.  * Colormapped mode is also useful for reducing grayscale output to a small
  134.  * number of gray levels: when using the 1-pass quantizer on grayscale data,
  135.  * the colormap entries will be evenly spaced from 0 to MAX_JSAMPLE, so you
  136.  * can regard the indexes are directly representing gray levels at reduced
  137.  * precision.  In any other case, you should not depend on the colormap
  138.  * entries having any particular order.
  139.  * To get colormapped output, set cinfo->quantize_colors to TRUE and set
  140.  * cinfo->desired_number_of_colors to the maximum number of entries in the
  141.  * colormap.  This can be done either in your main routine or in
  142.  * d_ui_method_selection.  For grayscale quantization, also set
  143.  * cinfo->two_pass_quantize to FALSE to ensure the 1-pass quantizer is used
  144.  * (presently this is the default, but it may not be so in the future).
  145.  *
  146.  * The output file writing modules (jwrppm.c, jwrgif.c, jwrtarga.c, etc) may be
  147.  * useful examples of what these routines should actually do, although each of
  148.  * them is encrusted with a lot of specialized code for its own file format.
  149.  */
  150.  
  151.  
  152. METHODDEF void
  153. output_init (decompress_info_ptr cinfo)
  154. /* This routine should do any setup required */
  155. {
  156.    struct NewVirtualDisplay nvd;
  157.    short i;
  158.    
  159.   /* This routine can initialize for output based on the data passed in cinfo.
  160.    * Useful fields include:
  161.    *    image_width, image_height    Pretty obvious, I hope.
  162.    *    data_precision            bits per pixel value; typically 8.
  163.    *    out_color_space            output colorspace previously requested
  164.    *    color_out_comps            number of color components in same
  165.    *    final_out_comps            number of components actually output
  166.    * final_out_comps is 1 if quantize_colors is true, else it is equal to
  167.    * color_out_comps.
  168.    *
  169.    * If you have requested color quantization, the colormap is NOT yet set.
  170.    * You may wish to defer output initialization until put_color_map is called.
  171.    */
  172.    if( glob_hires ) {
  173.       nvd.DWidth = min(VIEWWIDTH,cinfo->image_width/2);
  174.       nvd.DHeight = min(VIEWHEIGHTHIRES,cinfo->image_height);
  175.       nvd.DLeft = VIEWXOFFSET+(VIEWWIDTH-nvd.DWidth)/2;
  176.       nvd.DTop = VIEWYOFFSET+(VIEWHEIGHTHIRES-nvd.DHeight)/2;
  177.       nvd.VBitMapWidth = cinfo->image_width/2;
  178.       nvd.Modes = HAM | LACE;
  179.    }
  180.    else {
  181.       nvd.DWidth = min(VIEWWIDTH,cinfo->image_width);
  182.       nvd.DHeight = min(VIEWHEIGHTLOWRES,cinfo->image_height);
  183.       nvd.DLeft = VIEWXOFFSET+(VIEWWIDTH-nvd.DWidth)/2;
  184.       nvd.DTop = VIEWYOFFSET+(VIEWHEIGHTLOWRES-nvd.DHeight)/2;
  185.       nvd.VBitMapWidth = cinfo->image_width;
  186.       nvd.Modes = HAM;
  187.    }
  188.    nvd.Depth = VIEWDEPTH;
  189.    nvd.VBXOffset = 0;
  190.    nvd.VBYOffset = 0;
  191.    nvd.VBitMapHeight = cinfo->image_height;
  192.    vdisp = OpenVirtualDisplay( &nvd );
  193.    if( vdisp == NULL ) error_exit("Can't open virtual display");
  194.    for(i = 0; i < USEDCOLORREG; i++)
  195.          SetRGB4(&(vdisp->ViewPort), i, i, i, i );
  196. }
  197.  
  198.  
  199. /*
  200.  * This routine is called if and only if you have set cinfo->quantize_colors
  201.  * to TRUE.  It is given the selected colormap and can complete any required
  202.  * initialization.  This call will occur after output_init and before any
  203.  * calls to put_pixel_rows.  Note that the colormap pointer is also placed
  204.  * in a cinfo field, whence it can be used by put_pixel_rows or output_term.
  205.  * num_colors will be less than or equal to desired_number_of_colors.
  206.  *
  207.  * The colormap data is supplied as a 2-D array of JSAMPLEs, indexed as
  208.  *        JSAMPLE colormap[component][indexvalue]
  209.  * where component runs from 0 to cinfo->color_out_comps-1, and indexvalue
  210.  * runs from 0 to num_colors-1.  Note that this is actually an array of
  211.  * pointers to arrays rather than a true 2D array, since C does not support
  212.  * variable-size multidimensional arrays.
  213.  * JSAMPLE is typically typedef'd as "unsigned char".  If you want your code
  214.  * to be as portable as the JPEG code proper, you should always access JSAMPLE
  215.  * values with the GETJSAMPLE() macro, which will do the right thing if the
  216.  * machine has only signed chars.
  217.  */
  218.  
  219. METHODDEF void
  220. put_color_map (decompress_info_ptr cinfo, int num_colors, JSAMPARRAY colormap)
  221. /* Write the color map */
  222. {
  223.   /* You need not provide this routine if you always set cinfo->quantize_colors
  224.    * FALSE; but a safer practice is to provide it and have it just print an
  225.    * error message, like this:
  226.    */
  227. }
  228.  
  229.  
  230. /*
  231.  * This function is called repeatedly, with a few more rows of pixels supplied
  232.  * on each call.  With the current JPEG code, some multiple of 8 rows will be
  233.  * passed on each call except the last, but it is extremely bad form to depend
  234.  * on this.  You CAN assume num_rows > 0.
  235.  * The data is supplied in top-to-bottom row order (the standard order within
  236.  * a JPEG file).  If you cannot readily use the data in that order, you'll
  237.  * need an intermediate array to hold the image.  See jwrrle.c for an example
  238.  * of outputting data in bottom-to-top order.
  239.  *
  240.  * The data is supplied as a 3-D array of JSAMPLEs, indexed as
  241.  *        JSAMPLE pixel_data[component][row][column]
  242.  * where component runs from 0 to cinfo->final_out_comps-1, row runs from 0 to
  243.  * num_rows-1, and column runs from 0 to cinfo->image_width-1 (column 0 is
  244.  * left edge of image).  Note that this is actually an array of pointers to
  245.  * pointers to arrays rather than a true 3D array, since C does not support
  246.  * variable-size multidimensional arrays.
  247.  * JSAMPLE is typically typedef'd as "unsigned char".  If you want your code
  248.  * to be as portable as the JPEG code proper, you should always access JSAMPLE
  249.  * values with the GETJSAMPLE() macro, which will do the right thing if the
  250.  * machine has only signed chars.
  251.  *
  252.  * If quantize_colors is true, then there is only one component, and its values
  253.  * are indexes into the previously supplied colormap.  Otherwise the values
  254.  * are actual data in your selected output colorspace.
  255.  */
  256.  
  257. #define RowBytes(cols)        ( ( ( (cols) + 15 ) / 16 ) * 2 )
  258.  
  259. short XxXx;
  260. #define abs(a) (XxXx=(a),XxXx>0?XxXx:-XxXx) 
  261. short YyYy;
  262. short ZzZz;
  263. #define min(a,b) (YyYy=(a),ZzZz=(b),YyYy<=ZzZz?YyYy:ZzZz)
  264.  
  265. METHODDEF void
  266. put_pixel_rows (decompress_info_ptr cinfo, int num_rows, JSAMPIMAGE pixel_data)
  267. /* Write some rows of output data */
  268. {
  269.    /* This example shows how you might write full-color RGB data (3 components)
  270.     * to an output file in which the data is stored 3 bytes per pixel.
  271.     */
  272.  
  273.    JSAMPROW r, g, b;
  274.    long col;
  275.    int row, rowoffset;
  276.    short plane, i, dr, dg, db, dl, depth;
  277.    UBYTE buf[8], red, grn, blu, lum, oldred, oldgrn, oldblu, oldlum;
  278.    PLANEPTR destrow[8], *planes;
  279.  
  280.    if( (*(UBYTE *)(0xbfe001) & 64) == 0 ) error_exit("");
  281.  
  282.    planes = vdisp->VirtualBitMap.Planes;
  283.    depth = vdisp->VirtualBitMap.Depth;
  284.  
  285.    if( glob_hires ) {
  286.       if (cinfo->out_color_space == CS_GRAYSCALE) {
  287.          for( row = 0; row < num_rows; row++ ) {
  288.             rowoffset = (row + vdisp->currow) * vdisp->VirtualBitMap.BytesPerRow;
  289.             for( plane = 0; plane < depth; plane++ )
  290.                destrow[plane] = planes[plane] + rowoffset;
  291.             r = pixel_data[0][row];
  292.             for( col = 0; col < vdisp->VirtualBitMap.BytesPerRow; col++ ) {
  293.                for( i = 0; i < 8; i++ ) {
  294.                   buf[i] = ( GETJSAMPLE(*r)+GETJSAMPLE(*(r+1)) )>>5;
  295.                   r+=2;
  296.                }
  297.                transpose( buf );
  298.                for( plane = 0; plane < depth; plane++ )
  299.                   destrow[plane][col] = buf[plane];
  300.             }
  301.          }
  302.       }
  303.       else if(cinfo->out_color_space == CS_RGB ) {
  304.          for( row = 0; row < num_rows; row++ ) {
  305.             rowoffset = (row + vdisp->currow) * vdisp->VirtualBitMap.BytesPerRow;
  306.             for( plane = 0; plane < depth; plane++ )
  307.                destrow[plane] = planes[plane] + rowoffset;
  308.             r = pixel_data[0][row];
  309.             g = pixel_data[1][row];
  310.             b = pixel_data[2][row];
  311.             oldred = oldgrn = oldblu = oldlum = 0;
  312.             for( col = 0; col < vdisp->VirtualBitMap.BytesPerRow; col++ ) {
  313.                for( i = 0; i < 8; i++ ) {
  314.                   red = ( GETJSAMPLE(*r)+GETJSAMPLE(*(r+1)) )>>5;
  315.                   grn = ( GETJSAMPLE(*g)+GETJSAMPLE(*(g+1)) )>>5;
  316.                   blu = ( GETJSAMPLE(*b)+GETJSAMPLE(*(b+1)) )>>5;
  317.                   lum = ( red*77 + grn*151 + blu*28 )>>8;
  318.                   r+=2;
  319.                   g+=2;
  320.                   b+=2;
  321.                   dr = abs(grn - oldgrn) + abs(blu - oldblu); 
  322.                   dg = abs(red - oldred) + abs(blu - oldblu);
  323.                   db = abs(red - oldred) + abs(grn - oldgrn);
  324.                   dl = abs(red - lum) + abs(grn -lum) + abs(blu - lum);
  325.                     if( (dl < dr && dl < dg && dl < db) || (abs(lum - oldlum) >= glob_treshold) ) {
  326.                         buf[i] = lum;
  327.                       oldred = oldgrn = oldblu = lum;
  328.                     }
  329.                    else if( db < dr && db < dg ) {
  330.                        buf[i] = CHANGEBLU | blu;
  331.                        oldblu = blu;
  332.                      }
  333.                     else if( dr < dg ) {
  334.                        buf[i] = CHANGERED | red;
  335.                        oldred = red;
  336.                      }
  337.                     else {
  338.                           buf[i] = CHANGEGRN | grn;
  339.                         oldgrn = grn;
  340.                      }
  341.                   oldlum = lum;
  342.               }
  343.               transpose( buf );
  344.               for( plane = 0; plane < depth; plane++ )
  345.                   destrow[plane][col] = buf[plane];
  346.            }
  347.         } 
  348.       }
  349.    }
  350.    else {
  351.       if (cinfo->out_color_space == CS_GRAYSCALE) {
  352.          for( row = 0; row < num_rows; row++ ) {
  353.             rowoffset = (row + vdisp->currow) * vdisp->VirtualBitMap.BytesPerRow;
  354.             for( plane = 0; plane < depth; plane++ )
  355.                destrow[plane] = planes[plane] + rowoffset;
  356.             r = pixel_data[0][row];
  357.             for( col = 0; col < vdisp->VirtualBitMap.BytesPerRow; col++ ) {
  358.                for( i = 0; i < 8; i++ ) {
  359.                   buf[i] = GETJSAMPLE(*r)>>4;
  360.                   r++;
  361.                }
  362.                transpose( buf );
  363.                for( plane = 0; plane < depth; plane++ )
  364.                   destrow[plane][col] = buf[plane];
  365.             }
  366.          }
  367.       }
  368.       else if(cinfo->out_color_space == CS_RGB ) {
  369.          for( row = 0; row < num_rows; row++ ) {
  370.             rowoffset = (row + vdisp->currow) * vdisp->VirtualBitMap.BytesPerRow;
  371.             for( plane = 0; plane < depth; plane++ )
  372.                destrow[plane] = planes[plane] + rowoffset;
  373.             r = pixel_data[0][row];
  374.             g = pixel_data[1][row];
  375.             b = pixel_data[2][row];
  376.             oldred = oldgrn = oldblu = oldlum = 0;
  377.             for( col = 0; col < vdisp->VirtualBitMap.BytesPerRow; col++ ) {
  378.                for( i = 0; i < 8; i++ ) {
  379.                   red = GETJSAMPLE(*r)>>4;
  380.                   grn = GETJSAMPLE(*g)>>4;
  381.                   blu = GETJSAMPLE(*b)>>4;
  382.                   lum = ( red*77 + grn*151 + blu*28 )>>8;
  383.                   r++;
  384.                   g++;
  385.                   b++;
  386.                   dr = abs(grn - oldgrn) + abs(blu - oldblu); 
  387.                   dg = abs(red - oldred) + abs(blu - oldblu);
  388.                   db = abs(red - oldred) + abs(grn - oldgrn);
  389.                   dl = abs(red - lum) + abs(grn -lum) + abs(blu - lum);
  390.  
  391.                     if( (dl < dr && dl < dg && dg < db) || (abs(lum - oldlum) >= glob_treshold) ) {
  392.                         buf[i] = lum;
  393.                       oldred = oldgrn = oldblu = lum;
  394.                     }
  395.                    else if( db < dr && db < dg ) {
  396.                        buf[i] = CHANGEBLU | blu;
  397.                        oldblu = blu;
  398.                      }
  399.                     else if( dr < dg ) {
  400.                        buf[i] = CHANGERED | red;
  401.                        oldred = red;
  402.                      }
  403.                     else {
  404.                           buf[i] = CHANGEGRN | grn;
  405.                         oldgrn = grn;
  406.                      }
  407.                   oldlum = lum;
  408.                }
  409.                transpose( buf );
  410.                for( plane = 0; plane < depth; plane++ )
  411.                   destrow[plane][col] = buf[plane];
  412.             }
  413.          } 
  414.       }
  415.    }
  416.    vdisp->currow += num_rows;
  417.  
  418.    vdisp->VBXOffset = min( mouse_x(), vdisp->VirtualBitMap.BytesPerRow - vdisp->BitMap.BytesPerRow );
  419.    vdisp->VBYOffset = min( 8*mouse_y(), vdisp->VirtualBitMap.Rows - vdisp->BitMap.Rows );
  420.    RefreshVirtualDisplay( vdisp );
  421. }
  422.  
  423. METHODDEF void
  424. output_term (decompress_info_ptr cinfo)
  425. /* Finish up at the end of the output */
  426. {
  427.    short x, y, oldx, oldy;
  428.  
  429.   /* This termination routine may not need to do anything. */
  430.   /* Note that the JPEG code will only call it during successful exit; */
  431.   /* if you want it called during error exit, you gotta do that yourself. */
  432.  
  433.    oldx = 0;
  434.    oldy = 0;
  435.    while( 1 ) {
  436.       x = min( mouse_x(), vdisp->VirtualBitMap.BytesPerRow - vdisp->BitMap.BytesPerRow );
  437.       y = min( 8*mouse_y(), vdisp->VirtualBitMap.Rows - vdisp->BitMap.Rows );
  438.       if( (*(UBYTE *)(0xbfe001) & 64) == 0 ) 
  439.          if( (x == 0) && (y == 0) )
  440.             break;
  441.          else
  442.             RefreshVirtualDisplay( vdisp );
  443.       if( x != oldx || y != oldy ) {
  444.          oldx = x;
  445.          oldy = y;
  446.          vdisp->VBXOffset = x; 
  447.          vdisp->VBYOffset = y;
  448.          RefreshVirtualDisplay( vdisp );
  449.       }
  450.    }
  451.    if( vdisp ) CloseVirtualDisplay( vdisp );
  452. }
  453.  
  454.  
  455. /*
  456.  * That's it for the routines that deal with writing the output image.
  457.  * Now we have overall control and parameter selection routines.
  458.  */
  459.  
  460.  
  461. /*
  462.  * This routine gets control after the JPEG file header has been read;
  463.  * at this point the image size and colorspace are known.
  464.  * The routine must determine what output routines are to be used, and make
  465.  * any decompression parameter changes that are desirable.  For example,
  466.  * if it is found that the JPEG file is grayscale, you might want to do
  467.  * things differently than if it is color.  You can also delay setting
  468.  * quantize_colors and associated options until this point. 
  469.  *
  470.  * j_d_defaults initializes out_color_space to CS_RGB.  If you want grayscale
  471.  * output you should set out_color_space to CS_GRAYSCALE.  Note that you can
  472.  * force grayscale output from a color JPEG file (though not vice versa).
  473.  */
  474.  
  475. METHODDEF void
  476. d_ui_method_selection (decompress_info_ptr cinfo)
  477. {
  478.   if( (cinfo->jpeg_color_space == CS_GRAYSCALE) || (glob_grayscale == TRUE) )
  479.     cinfo->out_color_space = CS_GRAYSCALE;
  480.   else
  481.     cinfo->out_color_space = CS_RGB;
  482.  
  483.   /* select output routines */
  484.   cinfo->methods->output_init = output_init;
  485.   cinfo->methods->put_color_map = put_color_map;
  486.   cinfo->methods->put_pixel_rows = put_pixel_rows;
  487.   cinfo->methods->output_term = output_term;
  488. }
  489.  
  490.  
  491. /*
  492.  * OK, here is the main function that actually causes everything to happen.
  493.  * We assume here that the JPEG filename is supplied by the caller of this
  494.  * routine, and that all decompression parameters can be default values.
  495.  * The routine returns 1 if successful, 0 if not.
  496.  */
  497.  
  498. GLOBAL int
  499. read_JPEG_file (char * filename)
  500. {
  501.   /* These three structs contain JPEG parameters and working data.
  502.    * They must survive for the duration of parameter setup and one
  503.    * call to jpeg_decompress; typically, making them local data in the
  504.    * calling routine is the best strategy.
  505.    */
  506.   struct decompress_info_struct cinfo;
  507.   struct decompress_methods_struct dc_methods;
  508.   struct external_methods_struct e_methods;
  509.  
  510.   /* Select the input and output files.
  511.    * In this example we want to open the input file before doing anything else,
  512.    * so that the setjmp() error recovery below can assume the file is open.
  513.    * Note that cinfo.output_file is only used if your output handling routines
  514.    * use it; otherwise, you can just make it NULL.
  515.    * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
  516.    * requires it in order to read binary files.
  517.    */
  518.  
  519.   if ((cinfo.input_file = fopen(filename, "rb")) == NULL) {
  520.     fprintf(stderr, "can't open %s\n", filename);
  521.     return 0;
  522.   }
  523.  
  524.   cinfo.output_file = NULL;    /* NULL if no actual output file involved */
  525.  
  526.   /* Initialize the system-dependent method pointers. */
  527.   cinfo.methods = &dc_methods;    /* links to method structs */
  528.   cinfo.emethods = &e_methods;
  529.   /* Here we supply our own error handler; compare to use of standard error
  530.    * handler in the previous write_JPEG_file example.
  531.    */
  532.   emethods = &e_methods;    /* save struct addr for possible access */
  533.   e_methods.error_exit = error_exit; /* supply error-exit routine */
  534.   e_methods.trace_message = trace_message; /* supply trace-message routine */
  535.  
  536.   /* prepare setjmp context for possible exit from error_exit */
  537.   if (setjmp(setjmp_buffer)) {
  538.     /* If we get here, the JPEG code has signaled an error.
  539.      * Memory allocation has already been cleaned up (see free_all call in
  540.      * error_exit), but we need to close the input file before returning.
  541.      * You might also need to close an output file, etc.
  542.      */
  543.     fclose(cinfo.input_file);
  544.     return 0;
  545.   }
  546.  
  547.   /* Here we use the standard memory manager provided with the JPEG code.
  548.    * In some cases you might want to replace the memory manager, or at
  549.    * least the system-dependent part of it, with your own code.
  550.    */
  551.   jselmemmgr(&e_methods);    /* select std memory allocation routines */
  552.   /* If the decompressor requires full-image buffers (for two-pass color
  553.    * quantization or a noninterleaved JPEG file), it will create temporary
  554.    * files for anything that doesn't fit within the maximum-memory setting.
  555.    * You can change the default maximum-memory setting by changing
  556.    * e_methods.max_memory_to_use after jselmemmgr returns.
  557.    * On some systems you may also need to set up a signal handler to
  558.    * ensure that temporary files are deleted if the program is interrupted.
  559.    * (This is most important if you are on MS-DOS and use the jmemdos.c
  560.    * memory manager back end; it will try to grab extended memory for
  561.    * temp files, and that space will NOT be freed automatically.)
  562.    * See jcmain.c or jdmain.c for an example signal handler.
  563.    */
  564.  
  565.   /* Here, set up the pointer to your own routine for post-header-reading
  566.    * parameter selection.  You could also initialize the pointers to the
  567.    * output data handling routines here, if they are not dependent on the
  568.    * image type.
  569.    */
  570.   dc_methods.d_ui_method_selection = d_ui_method_selection;
  571.  
  572.   /* Set up default decompression parameters. */
  573.   j_d_defaults(&cinfo, TRUE);
  574.   /* TRUE indicates that an input buffer should be allocated.
  575.    * In unusual cases you may want to allocate the input buffer yourself;
  576.    * see jddeflts.c for commentary.
  577.    */
  578.  
  579.   /* At this point you can modify the default parameters set by j_d_defaults
  580.    * as needed; for example, you can request color quantization or force
  581.    * grayscale output.  See jdmain.c for examples of what you might change.
  582.    */
  583.  
  584.    cinfo.quantize_colors = FALSE;
  585.    cinfo.desired_number_of_colors = 256;
  586.    cinfo.two_pass_quantize = FALSE;
  587.    cinfo.use_dithering = FALSE;
  588.    cinfo.do_block_smoothing = glob_block_smoothing;
  589.    cinfo.do_pixel_smoothing = glob_pixel_smoothing;
  590.  
  591.   /* Set up to read a JFIF or baseline-JPEG file. */
  592.   /* This is the only JPEG file format currently supported. */
  593.   jselrjfif(&cinfo);
  594.  
  595.   /* Here we go! */
  596.   jpeg_decompress(&cinfo);
  597.  
  598.   /* That's it, son.  Nothin' else to do, except close files. */
  599.   /* Here we assume only the input file need be closed. */
  600.   fclose(cinfo.input_file);
  601.  
  602.   return 1;            /* indicate success */
  603.  
  604.   /* Note: if you want to decompress more than one image, we recommend you
  605.    * repeat this whole routine.  You MUST repeat the j_d_defaults()/alter
  606.    * parameters/jpeg_decompress() sequence, as some data structures allocated
  607.    * in j_d_defaults are freed upon exit from jpeg_decompress.
  608.    */
  609. }
  610.  
  611.